package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationTypeEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIotConfigProperties;
import com.zzyl.service.DeviceSerVice;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class DeviceSerViceimpl implements DeviceSerVice {

    @Autowired
    private Client client;

    @Autowired
    private AliIotConfigProperties aliIotConfigProperties;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void getSyncProductList() {
        System.out.println(aliIotConfigProperties);
        //创建调用方法所需的参数对象 并设置公共实例id和页码以及条数
        QueryProductListRequest request = new QueryProductListRequest();
        request.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        request.setPageSize(200);
        request.setCurrentPage(1);
        QueryProductListResponse queryProductListResponse = null;
        try {
           queryProductListResponse = client.queryProductList(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //判断是否成功执行 如果成功执行获取数据并存储到redis中
        if (queryProductListResponse.getBody().success){
            List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfo = queryProductListResponse.getBody().getData().getList().getProductInfo();
            redisTemplate.opsForValue().set(CacheConstants.PUBLIC_PRODUCT_LIST, JSONUtil.toJsonStr(productInfo));
        }
    }

    @Override
    public List<ProductVo> getProductList() {
        String ProductJson = redisTemplate.opsForValue().get(CacheConstants.PUBLIC_PRODUCT_LIST);
        List<ProductVo> list = JSONUtil.toList(ProductJson, ProductVo.class);
        return list;
    }

    @Override
    public void RegisterDevice(DeviceDto deviceDto) {
        //1.判断设备名称是否重复
        int count = deviceMapper.selectCountByDeviceName(deviceDto.getDeviceName());
        if (count > 0) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        //2.iot物联网平台新增设备
        RegisterDeviceRequest registerDeviceRequest = new RegisterDeviceRequest();
        registerDeviceRequest.setProductKey(deviceDto.getProductKey());
        registerDeviceRequest.setDeviceName(deviceDto.getDeviceName());
        registerDeviceRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        RegisterDeviceResponse registerDeviceResponse;
        try {
            registerDeviceResponse = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        //获取新增设备的iotId 并设置到deviceDto中
        String iotId = registerDeviceResponse.getBody().getData().getIotId();
        deviceDto.setIotId(iotId);
        //判断接口是否调通
        if (!registerDeviceResponse.getBody().getSuccess()){
            throw new RuntimeException(registerDeviceResponse.getBody().getErrorMessage());
        }
        //3.查询注册设备对应的产品 设置产品名称到设备对象
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        queryProductRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        QueryProductResponse queryProductResponse;
        try {
            queryProductResponse = client.queryProduct(queryProductRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }
        //判断接口是否调通
        if (!queryProductResponse.getBody().success){
            throw new RuntimeException(queryProductResponse.getBody().getErrorMessage());
        }
        deviceDto.setProductName(queryProductResponse.getBody().getData().getProductName());
        //4.判断位置类型是否是0 随身设备 如果是将物理设置设为-1
        if (deviceDto.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())){
            deviceDto.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }
        //5.转换成实体类
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setHaveEntranceGuard(0);
        //6.保存设备到数据库 如果保存失败需要把iot物联网平台的新增设备也删除
        try {
            deviceMapper.insertDevice(device);
        } catch (Exception e) {
            e.printStackTrace();
            //iot物联网平台删除设备
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setProductKey(deviceDto.getProductKey());
            deleteDeviceRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
            deleteDeviceRequest.setDeviceName(deviceDto.getDeviceName());
            deleteDeviceRequest.setIotId(deviceDto.getIotId());
            DeleteDeviceResponse deleteDeviceResponse;
            try {
                deleteDeviceResponse = client.deleteDevice(deleteDeviceRequest);
            } catch (Exception ex) {
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
            //判断接口是否调通
            if (!deleteDeviceResponse.getBody().success){
                throw new RuntimeException(deleteDeviceResponse.getBody().getErrorMessage());
            }
            //如果代码正确 保存失败的情况就只能是相同的位置绑定了同一个类型的产品
            throw new BaseException(BasicEnum.RE_SELECT_PRODUCT);
        }
    }

    @Override
    public PageResponse queryPageDevice(DevicePageQueryDto devicePageQueryDto) {
        //1.设置分页条件
        PageHelper.startPage(devicePageQueryDto.getPageNum(),devicePageQueryDto.getPageSize());
        //2.调用mapper根据条件去数据库查询设备
        Page<DeviceVo> deviceVos = deviceMapper.queryPageDevice(devicePageQueryDto);
        //3.转换成PageResponse返回
        return PageResponse.of(deviceVos,DeviceVo.class);

    }

    @Override
    public DeviceVo QueryDeviceDetail(DeviceDto deviceDto) {
        //1.根据产品和设备查询详情 需要到iot物联网平台
        QueryDeviceDetailRequest queryDeviceDetailRequest = new QueryDeviceDetailRequest();
        queryDeviceDetailRequest.setProductKey(deviceDto.getProductKey());
        queryDeviceDetailRequest.setIotId(deviceDto.getIotId());
        queryDeviceDetailRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        QueryDeviceDetailResponse queryDeviceDetailResponse;
        try {
            queryDeviceDetailResponse = client.queryDeviceDetail(queryDeviceDetailRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        //判断物联网接口是否调通
        if (!queryDeviceDetailResponse.getBody().success){
            throw new RuntimeException(queryDeviceDetailResponse.getBody().getErrorMessage());
        }
        //2.根据设备id到数据库查询设备
        DeviceVo deviceVo = deviceMapper.selectDeviceByiotId(deviceDto.getIotId());
        if (ObjectUtil.isEmpty(deviceVo)) {
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST_QUERY);
        }
        //3.合并数据并返回
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = queryDeviceDetailResponse.getBody().getData();
        BeanUtil.copyProperties(data, deviceVo, CopyOptions.create().ignoreNullValue());
        return BeanUtil.toBean(deviceVo,DeviceVo.class);
    }

    @Override
    public QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData queryDeviceStatus(DeviceDto deviceDto) {
        Device device = deviceMapper.selectByDeviceName(deviceDto.getDeviceName());
        //1.到iot物联网平台查询指定设备的物模型运行状态
        QueryDevicePropertyStatusRequest queryDevicePropertyStatusRequest = new QueryDevicePropertyStatusRequest();
        queryDevicePropertyStatusRequest.setDeviceName(deviceDto.getDeviceName());
        queryDevicePropertyStatusRequest.setProductKey(deviceDto.getProductKey());
        queryDevicePropertyStatusRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse queryDevicePropertyStatusResponse;
        try {
            queryDevicePropertyStatusResponse = client.queryDevicePropertyStatus(queryDevicePropertyStatusRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }
        //判断接口是否调通
        if (!queryDevicePropertyStatusResponse.getBody().success){
            throw new RuntimeException(queryDevicePropertyStatusResponse.getBody().getErrorMessage());
        }
//        QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyDataList list = queryDevicePropertyStatusResponse.getBody().getData().getList();
        QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData data = queryDevicePropertyStatusResponse.getBody().getData();
        return data;
    }

    @Override
    public Map<String, String> QueryThingModelPublished(DeviceDto deviceDto) {
        //调用阿里云对应接口查询已发布物模型中的功能定义详情
        QueryThingModelPublishedRequest queryThingModelPublishedRequest = new QueryThingModelPublishedRequest();
        queryThingModelPublishedRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        queryThingModelPublishedRequest.setProductKey(deviceDto.getProductKey());
        QueryThingModelPublishedResponse queryThingModelPublishedResponse;
        try {
            queryThingModelPublishedResponse = client.queryThingModelPublished(queryThingModelPublishedRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        //判断接口是否调通
        if (!queryThingModelPublishedResponse.getBody().success){
            throw new RuntimeException(queryThingModelPublishedResponse.getBody().getErrorMessage());
        }
        String thingModelJson = queryThingModelPublishedResponse.getBody().getData().getThingModelJson();
        Map<String,String> thingModelMap = new HashMap<String,String>();
        thingModelMap.put("thingModelJson",thingModelJson);
        return thingModelMap;
    }

    @Override
    public void UpdateDevice(DeviceDto deviceDto) {
        QueryDeviceRequest queryDeviceRequest = new QueryDeviceRequest();
        queryDeviceRequest.setProductKey(deviceDto.getProductKey());
        queryDeviceRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        queryDeviceRequest.setCurrentPage(1);
        queryDeviceRequest.setPageSize(10);
        QueryDeviceResponse queryDeviceResponse;
        try {
            queryDeviceResponse = client.queryDevice(queryDeviceRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        System.out.println(JSONUtil.toJsonStr(queryDeviceResponse.getBody().getData()));
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        //1.调用阿里云对应修改接口方法
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();

        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> NicknameInfos = new ArrayList<>();
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nikeNameInfo = new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();
        nikeNameInfo.setDeviceName(device.getDeviceName());
        nikeNameInfo.setNickname(device.getNickname());
        nikeNameInfo.setProductKey(device.getProductKey());
        nikeNameInfo.setIotId(device.getIotId());
        NicknameInfos.add(nikeNameInfo);
        request.setDeviceNicknameInfo(NicknameInfos);
        request.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        BatchUpdateDeviceNicknameResponse batchUpdateDeviceNicknameResponse;
        try {
            batchUpdateDeviceNicknameResponse = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
        //判断接口是否调通
        if (!batchUpdateDeviceNicknameResponse.getBody().success){
            throw new RuntimeException(batchUpdateDeviceNicknameResponse.getBody().getErrorMessage());
        }
        //2.修改数据库中的设备信息
        int count = deviceMapper.UpdateDevice(device);
        //判断是否修改成功
        if (count == 0) {
            throw new RuntimeException("数据库修改设备失败");
        }
    }

    @Override
    public void deleteDevice(DeviceDto deviceDto) {
        //1.调用阿里云物联网平台删除设备接口
        DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
        deleteDeviceRequest.setProductKey(deviceDto.getProductKey());
        deleteDeviceRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        deleteDeviceRequest.setIotId(deviceDto.iotId);
        DeleteDeviceResponse deleteDeviceResponse;
        try {
            deleteDeviceResponse = client.deleteDevice(deleteDeviceRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }

        //判断接口是否调通
        if (deleteDeviceResponse.getBody().success){
            int count = deviceMapper.deleteDeviceByiotId(deviceDto.getIotId());
            if (count == 0) {
                throw new RuntimeException("数据库删除设备失败");
            }
        }
    }
}
